import { _decorator, AssetManager, Color, Component, error, EventTouch, find, ImageAsset, instantiate, Label, native, Node, NodeEventType, Prefab, resources, Sprite, SpriteFrame, sys, Texture2D, tween, Vec3 } from 'cc';
import CryptoJS from 'crypto-js';
import { GLOBALVar } from './GlobalVar';
const { ccclass, property } = _decorator;

@ccclass('GlobalUtil')
class GlobalUtil{
    static _instance:GlobalUtil = null;
    public static getInstance():GlobalUtil{
        if(this._instance == null){
            this._instance = new GlobalUtil();
        }
        return this._instance;
    }

    //生成1个随机整数, [0,m) m不可取
    public getSingleRandomInt(m:number):number{
        return Math.floor(Math.random() * m);
    }

    //生成多个随机整数(不重复). count:随机数个数, [n,m)为可取范围, m不可取
    public getMultiRandomInt(count:number, n:number, m:number) {
        if (count > m - n) {
            console.error("随机数取值数量大于可取数量");
            return;
        }
        let arr: number[] = [];
        for (let i = 0; i < count; i++) {
            let num = Math.floor(Math.random() * (m - n) + n);
            while (arr.indexOf(num) != -1) {
                num = Math.floor(Math.random() * (m - n) + n);
            }
            arr.push(num);
        }
        return arr;
    }

    //加载消息弹窗提示
    private MessageEntity: Node = null;
    private timeoutId: any = null;
    public LoadMessage(isAutoClose: boolean, msg:string, parent: Node, targetlPos: Vec3 = new Vec3(50, 950, 0), isDestroyOldBeforeGenNewOne: boolean = true, messageType: number = 0, initialPos = new Vec3(-300, 950, 0), color: Color = new Color(255,255,255,255)) {
        let node: Node;
        if (isDestroyOldBeforeGenNewOne) {
            if (this.MessageEntity != null) {
                this.MessageEntity.destroy();
                this.MessageEntity = null;
                clearTimeout(this.timeoutId);
            }
        }
        let promise = new Promise((resolve, reject) => {
            resources.load("Prefabs/MessagePop" + messageType, Prefab, (err, prefab) => {
                if (err) {
                    console.error(err);
                    reject(err);
                } else {
                    node = instantiate(prefab);
                    node.parent = parent;
                    node.setWorldPosition(initialPos);
                    let label = node.getChildByName("Context").getComponent(Label);
                    label.string = msg;
                    label.color = color;
                    tween(node).to(0.3, {worldPosition: targetlPos}).start();
                    //点击关闭事件
                    let panel = node.getChildByName("ConversationPanel_000");
                    panel.on(NodeEventType.TOUCH_END, () => {
                        node.destroy();
                        this.MessageEntity = null;
                    })
                    if(isAutoClose){
                        //七秒后自动销毁
                        this.timeoutId = setTimeout(() => {
                            node.destroy();
                            this.MessageEntity = null;
                        }, 7000);
                    }
                    this.MessageEntity = node;
                    resolve(node);
                }
            })
        });
        return promise;
    }

    //密码哈希加密
    public hashPassword(password: string): string {
        return CryptoJS.SHA256(password).toString();
    }
    public validateEmail(email: string): boolean {
        // 正则表达式用于校验邮箱格式
        const regex: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
        return regex.test(email);
    }
    
    //判断字符串是否纯空格组成
    public isBlankString(str: string): boolean {
        return /^\s*$/.test(str);
    }


    //计算字符串长度
    public calculateStringLength(str: string): number {
        let length = 0;
        for (let i = 0; i < str.length; i++) {
            // 判断字符是否为 ASCII 字符
            if (str.charCodeAt(i) <= 127) {
                length += 1;
            } else {
                length += 2;
            }
        }
        return length;
    }

    public handleImageSelect(callback: (imageAsset: ImageAsset) => void) {
        //判断请求是来自原生平台还是web平台, 实现对两种平台的支持
        if (sys.isBrowser) {
            this.handleWebImageSelect(callback);
        }
        if (sys.isNative && sys.os === sys.OS.ANDROID) {
            this.handleMobileImageSelect();
        }
    };

    private handleWebImageSelect(callback: (imageAsset: ImageAsset) => void) {
        console.log("This is a web platform");
    
        // 创建一个 input 元素用于选择文件
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = 'image/*';
    
        // 监听文件选择事件
        input.addEventListener('change', () => {
            const files = input.files;
            if (files && files.length > 0) {
                const file = files[0];
                const reader = new FileReader();
    
                // 监听文件读取完成事件
                reader.addEventListener('load', () => {
                    // 获取读取到的图片数据（base64 字符串）
                    const imageData = reader.result as string;
                    const img = new Image();
                    img.src = imageData;
                    img.onload = () => {
                        // 创建 ImageAsset 实例
                        const imageAsset = new ImageAsset(img);
                        callback(imageAsset);
                    };
                });
    
                // 读取文件为 DataURL
                reader.readAsDataURL(file);
            }
        });
    
        // 触发文件选择对话框
        input.click();
    };
    
    private handleMobileImageSelect() {
        native.reflection.callStaticMethod("com/cocos/game/AppActivity", "getImgPath", "()V");
    }

    
    


/**********************************************************网络请求*******************************************************/
    //网络消息
    public sendXMLMessage(MessageType: string, Address: string, async: boolean, data?: any, dataType?: any): Promise<XMLHttpRequest> {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            let isRejected = false; // 标志变量，防止多次 reject
            xhr.open(MessageType, Address, async);
            xhr.timeout = 2000;
            //当请求超时时XMLHttpRequest会将readyState设置为4,触发onreadystatechange事件,随后才会触发ontimeout事件，此时xhr.status为0(因为请求被终止)
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {  //确保readyState == 4完成后再决定是resolve还是reject，不然在readyState == 1的时候就直接reject了。
                    if (isRejected) return;
                    if (xhr.status == 200) {
                        resolve(xhr);
                    } else if (xhr.status == 0) {
                        return;
                    } else {
                        isRejected = true;
                        console.error('Error', xhr.status, xhr.statusText);
                        reject(new Error(xhr.responseText));
                    }
                }
            };
            //发生错误的时候处理错误
            xhr.onerror = function () {
                if (isRejected) return;
                isRejected = true;
                reject(new Error('Network error'));
            };

            xhr.ontimeout = function () {
                if (isRejected) return;
                isRejected = true;
                reject(new Error('服务器错误，请求超时'));
            };
            //为登录注册以外的操作添加token
            const SkipPaths = ['/Login'];    //后续可拓展不需要添加token的情况
            const shouldSkipToken = !SkipPaths.some(path => Address.includes(path));
            if (shouldSkipToken) {
                const token = localStorage.getItem('token');
                if (token) {
                    xhr.setRequestHeader("Authorization", token);
                } else {
                    console.error('token is null')
                }
            }
                
            if (MessageType == 'POST') {
                if (typeof data == 'object') {
                    if (dataType == 'formData') {
                        xhr.send(data);
                    } else if (dataType == 'Uint8Array') {
                        xhr.setRequestHeader("Content-Type", "application/octet-stream");
                        xhr.send(data);
                    } else {
                        xhr.setRequestHeader("Content-Type", "application/json");
                        xhr.send(JSON.stringify(data));
                    }
                } else if (typeof data == 'number') {
                    xhr.setRequestHeader("Content-Type", "text/plain");
                    xhr.send(data.toString());
                } else {
                    xhr.setRequestHeader("Content-Type", "text/plain");
                    xhr.send(data);
                }
            } else if (MessageType == 'GET') {
                xhr.send();
            };
        })
    }

    //请求登录
    public requestLogin(LoginData) {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("POST", GLOBALVar.SERVER_ADDRESS + "/Login/RequestLogin", true, LoginData)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }

    // 利用本地储存的token来登录验证（免密码，有效期为七天）
    public requestLoginByToken() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("GET", GLOBALVar.SERVER_ADDRESS + "/UserData/_LoginByToken", true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }
    //获取用户个人信息（头像，昵称等除物品以外的数据）
    public getUserInfo() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("GET", GLOBALVar.SERVER_ADDRESS + "/UserData/getUserInfo", true)
            .then((xhr) => {
                //获取成功
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                reject(error);
            })
        })
    }

    //获取拥有卡套信息
    public getCardFrame() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("GET", GLOBALVar.SERVER_ADDRESS + "/UserData/getCardFrame", true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                reject(error);
            })
        })
    }
    //获取当前使用中的卡套
    public getCardFrameUsed() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("GET", GLOBALVar.SERVER_ADDRESS + "/UserData/getCardFrameUsed", true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response.msg);
            }).catch(error => {
                reject(error);
            })
        })
    }
    //使用卡套
    public setCardFrame(ItemID: number) {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("POST", GLOBALVar.SERVER_ADDRESS + "/UserData/setCardFrame", true, ItemID)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                reject(error);
            })
        })
    }

    //加载网络图片
    public loadNetImage(avatar_url: string, onComplete: (Sp: SpriteFrame) => void) {
        AssetManager.instance.loadRemote(GLOBALVar.SERVER_ADDRESS + avatar_url, (err, img: ImageAsset) => {
            if (err) {
                console.log(err);
            } else {
                const texture2d = new Texture2D();
                texture2d.image = img;
                const Sp = new SpriteFrame();
                Sp.texture = texture2d;
                //资源加载完成后执行，自带一个生成好的SpriteFrame参数。
                onComplete(Sp);
            }
        })
    }
    //刷新金币信息
    public refreshCoins(onComplete: () => void) {
        this.sendXMLMessage("GET", GLOBALVar.SERVER_ADDRESS + "/UserData/refreshCoins", true)
        .then((xhr) => {
            const response = JSON.parse(xhr.response);
            GLOBALVar.setCoins(response.coins);
            onComplete();
        }).catch(error => {
            console.error(error);
        })
    }
    //请求购买物品
    public requestBuyItem(itemId: number, itemNum: number) {
        return new Promise((resolve, reject) => {
            const data = {
                itemId: itemId,
                itemNum: itemNum,
            }
            this.sendXMLMessage("POST", GLOBALVar.SERVER_ADDRESS + "/UserData/buyItem", true, data)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }

    //上传新昵称
    public uploadNickname(Nickname: string) {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("POST", GLOBALVar.SERVER_ADDRESS + "/UserData/uploadNickname", true, Nickname)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }

    //上传新头像
    public uploadAvatar(Avatar: Blob) {
        return new Promise((resolve, reject) => {
            let formData = new FormData();
            formData.append("Avatar", Avatar);
            this.sendXMLMessage("POST", GLOBALVar.SERVER_ADDRESS + "/FileUpload/uploadAvatar", true, formData, 'formData')
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }

    //原生Android中把Uint8Array像素数据上传到服务器（最终的头像为方形）
    public uploadAvatarByAndroid(Avatar: Uint8Array) {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage("POST", GLOBALVar.SERVER_ADDRESS + "/FileUpload/uploadAvatarByAndroid", true, Avatar, 'Uint8Array')
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }

    //获取金币排名前50的玩家
    public getCoinTop50() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage('GET', GLOBALVar.SERVER_ADDRESS + '/UserData/getCoinTop50', true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        });
    }

    //通过user_id获取用户信息
    public getUserInfoByUserID(user_id: number) {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage('POST', GLOBALVar.SERVER_ADDRESS + '/UserData/getUserInfoByUserID', true, user_id)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
                reject(error);
            })
        })
    }

    //发送反馈
    public sendFeedback(content: string) {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage('POST', GLOBALVar.SERVER_ADDRESS + '/UserData/Feedback', true, content)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
            })
        })
    }

    //通关（虽然知道这样写会有安全风险但是懒得处理的）（解决方法是把通关的逻辑判断放在服务器）
    public updateVictory() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage('GET', GLOBALVar.SERVER_ADDRESS + '/UserData/victory', true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
            })
        })
    }

    //使用XMLHttpRequest增加金币
    public addCoin() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage('GET', GLOBALVar.SERVER_ADDRESS + '/UserData/AddCoin', true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
            })
        })
    }

    //获取公告内容
    public getNotice() {
        return new Promise((resolve, reject) => {
            this.sendXMLMessage('GET', GLOBALVar.SERVER_ADDRESS + '/System/getNotice', true)
            .then((xhr) => {
                const response = JSON.parse(xhr.response);
                resolve(response);
            }).catch(error => {
                console.error(error);
            })
        })
    }
}
export const GLOBALUtil = GlobalUtil.getInstance();